#define _GNU_SOURCE
#include <MQTTClient.h>
#include "app_mqtt.h"
#include "log/log.h"
#include <unistd.h>
#include <assert.h>

static int (*recv_callback)(char *, int);
static  MQTTClient client;
static MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

// 发送消息成功
static  void delivered(void *context, MQTTClient_deliveryToken dt)
{
    assert(context == NULL);
    log_debug("发送消息成功, dt=%d", dt);
}
 
static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    assert(context == NULL);
    log_debug("收到消息: %s, 长度：%d, tid=%d", message->payload, message->payloadlen, gettid());
    int result = 0;
    // 如果设置了接收消息的回调函数，则调用回调函数处理消息
    if (recv_callback)
    {
        result = recv_callback(message->payload, message->payloadlen)==0 ? 1 : 0;
    }
    
    // 释放消息
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);

    return result; // 1表示消息已成功处理  否则会出错
}
 
static void connlost(void *context, char *cause)
{
    assert(context == NULL);
    log_debug("连接断开，原因：%s", cause);
}

/**
 * @brief 初始化MQTT客户端
 */
int app_mqtt_init()
{
    log_debug("app_mqtt_init 主线程id=%d", gettid());
    // 初始化MQTT客户端
    if (MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_create failed");
        return -1;
    }
    // 设置回调函数
    MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);

    // 连接MQTT服务器
    // conn_opts.keepAliveInterval = 20;
    // conn_opts.cleansession = 1;
   if ( MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS)  // &conn_opts必须指定
    {
        log_error("MQTTClient_connect failed");
        MQTTClient_destroy(&client);
        return -1;
    }

    // 订阅PULL的主题
    if (MQTTClient_subscribe(client, TOPIC_PULL, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_subscribe failed");
        app_mqtt_close();
        return -1;
    }

    return 0;
}

/**
 * 关闭MQTT客户端
 */
void app_mqtt_close()
{
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
}

/**
 * 发送消息
 */
int app_mqtt_sendMsg(char *data, int len)
{
    // 指定要携带的数据和长度
    pubmsg.payload = data;
    pubmsg.payloadlen = len;
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
    int token;
    // 发布消息
    
    MQTTClient_publishMessage(client, TOPIC_PUSH, &pubmsg, &token);
    return 0;
}

/**
 * 设置用于接收消息的回调函数
 */
void app_mqtt_setRecvCallback(int (*callback)(char *, int))
{
    recv_callback = callback;
}